package object.connector;

import force.Force;
import object.mass.Mass;
import sim.Simulation;


/**
 * A spring that maintains a fixed length, using a high K constant
 * and damping.
 * @author Niel Lebeck and Wynne Lok
 *
 */
public class Bar extends Spring {
    private static final double DAMPING_FACTOR = 0.1;
    private static final double BAR_K = 20;

    /**
     * Creates a Bar, with a rest length set to the distance between
     * its Masses.
     * @param start starting Mass
     * @param end ending Mass
     * @param length is ignored
     * @param kVal is ignored
     */
    public Bar (Mass start, Mass end, double length, double kVal) {
        super(start, end,
                Force.distanceBetween(
                        end.getCenter().getX() - start.getCenter().getX(),
                        end.getCenter().getY() - start.getCenter().getY()),
                        BAR_K);
    }

    @Override
    public void update (Simulation canvas, double dt) {
        double dx = getDx();
        double dy = getDy();

        //get the relative velocity of the masses along the bar's axis
        Force barAxis = new Force(Force.angleBetween(dx, dy), 1);
        Force relVelocity = getDifference(this.getStart().getVelocity(),
                this.getEnd().getVelocity());
        double velProjMag = relVelocity.getRelativeMagnitude(barAxis);

        //apply the damping force
        Force damping = new Force(Force.angleBetween(dx, dy),
                DAMPING_FACTOR * velProjMag);
        damping.negate();

        this.getStart().applyForce(damping);
        damping.negate();
        this.getEnd().applyForce(damping);

        //apply the spring force
        super.update(canvas, dt);
    }

    /**
     * Takes the difference between two Forces and returns the resulting
     * Force, without modifying either of the two original forces.
     * @param force1 a force
     * @param force2 another force
     * @return the difference between force1 and force2
     */
    public Force getDifference(Force force1, Force force2) {
        Force diff = new Force(force1.getDirection(),
                force1.getMagnitude());
        Force relVelocity = new Force(force2.getDirection(),
                force2.getMagnitude());
        relVelocity.difference(diff);
        return relVelocity;
    }

}
